# coding=utf-8
from django import template
from django.core.paginator import Paginator
from django.db.models import Manager, Q
from django.utils.safestring import SafeText
from mezzanine.conf import settings
from article.models import Category, Article

register = template.Library()


@register.inclusion_tag('article/article_front.html', name='article_front')
def category_front(parent=None, *args, **kwargs):
    '''
    显示分类首页
    用法举例：article_front only_top_category=False latest=False featured_list_count=20
    '''
    preview = kwargs.pop('preview', False)
    result = dict()
    result['only_top_category'] = bool(kwargs['only_top_category']) if 'only_top_category' in kwargs else True

    qs = Category.objects.published()
    result['category_list'] = qs
    if kwargs.pop('show_latest', True):
        result['latest_list'] = Article.objects.published().order_by('-id')[0:kwargs.pop('latest_list_count', 10)]

    return result


@register.inclusion_tag('article/category_block.html')
def category_block(category, *args, **kwargs):
    '''
    显示分类的文章块
    用法举例:
        category_block 1
        category_block news
        category_block category
        .........................css = ...
    '''
    category, size = _parse_category_fetch_size(category, *args, **kwargs)
    return {'category': category, 'css': kwargs.get('css', None), 'MEDIA_URL': settings.MEDIA_URL}


@register.assignment_tag(name='load_article')
def load_article(*args):
    '''
    加载文章
    用法举例 load_article 1 as article
    '''
    id_or_slug = args[0]
    try:
        instance = Article.objects.published().get(id=id_or_slug)
    except Article.DoesNotExist:
        instance = Article.objects.published().get(slug=id_or_slug)
    return instance


@register.assignment_tag
def load_previous_article(article):
    return article.get_previous()


@register.assignment_tag
def load_next_article(article):
    return article.get_next()


@register.inclusion_tag('pages/article_detail.html', name='article')
def article(article):
    '''
    显示文章
    '''
    return {'object': article}


def _parse_category_fetch_size(*args, **kwargs):
    category = None
    if len(args) == 2:
        try:
            size = int(args[1])
        except ValueError:
            size = kwargs.get('size', 10)
    else:
        size = kwargs.get('size', 10)
    if len(args) >= 1:
        category = args[0]
        try:
            if isinstance(category, int):
                category = Category.objects.published().get(id=category)
            elif isinstance(category, SafeText):
                category = Category.objects.published().get(Q(slug=category) | Q(slug__endswith='/%s' % category))
            elif isinstance(category, Category):
                pass
        except Category.DoesNotExist:
            category = None
    return category, size


@register.inclusion_tag('article/article_list.html', name='article_list_for_category')
def article_list_for_category(category, *args, **kwargs):
    '''
    显示特定分类的文章
    用法举例:
        article_list_for_category 1
        article_list_for_category news
        article_list_for_category category
        ....................................... page page_size
    用法1 显示所有文章；
    用法2、3、4 显示指定分类及其子分类的文章
    用法5 指定获取的文章数量
    '''
    page = 1
    page_size = 10
    if len(args) >= 1:
        try:
            page = int(args[0])
        except ValueError:
            page = 1
    if len(args) == 2:
        try:
            page_size = int(args[1])
        except:
            page_size = 10
    try:
        if isinstance(category, int):
            category = Category.objects.published().get(id=category)
        elif isinstance(category, SafeText):
            category = Category.objects.published().get(slug=category)
        elif isinstance(category, Category):
            pass
        else:
            raise template.TemplateSyntaxError(
                u'article_list_for_category tag only accept pk,slug,category as argument')
        paginator = Paginator(category.article_set.all(), page_size)
        return {'article_list': paginator.page(page).object_list}
    except Category.DoesNotExist:
        return {'article_list': None}


@register.assignment_tag
def get_latest_covered_article(*args, **kwargs):
    '''
    获取最新的具有封面的文章。
    用法：
        get_last_covered_article
        get_last_covered_article 1
        get_last_covered_article news
        get_last_covered_article category include_children=False
    '''
    category, size = _parse_category_fetch_size(*args, **kwargs)
    if category:
        if kwargs.get('include_children', False):
            categories = list(category.children.all())
        else:
            categories = []
        categories.append(category)
        qs = Article.objects.filter(categories__in=categories, cover__isnull=False).exclude(cover='').order_by(
            '-publish_date')
    else:
        qs = Article.objects.filter(cover__isnull=False).exclude(cover='').order_by('-publish_date')
    if qs.exists():
        return qs[0]
    else:
        return None


@register.inclusion_tag('article/latest.html')
def latest_articles(*args, **kwargs):
    '''
    获取最新文章
    用法举例:
        latest_articles
        latest_articles 1
        latest_articles news
        latest_articles category
        ........................ size = 10, exclude = article
    用法1 显示所有最新文章；
    用法2、3、4 显示指定分类及其子分类的最新文章
    用法5 指定获取的文章数量,及排除的文章
    '''
    category, size = _parse_category_fetch_size(*args, **kwargs)
    if category:
        if kwargs.get('include_children', False):
            categories = list(category.children.all())
        else:
            categories = []
        categories.append(category)
        qs = Article.objects.filter(categories__in=categories).order_by('-publish_date')
    else:
        qs = Article.objects.order_by('-publish_date')
    exclude = kwargs.get('exclude', None)
    if exclude:
        if isinstance(exclude, Article):
            exclude = exclude.id
        elif isinstance(exclude, SafeText):
            try:
                exclude = Article.objects.get(slug=exclude).id
            except Article.DoesNotExist:
                exclude = None
        elif isinstance(exclude, int):
            try:
                Article.objects.get(id=exclude)
            except Article.DoesNotExist:
                exclude = None
        if exclude:
            qs = qs.exclude(id=exclude)
    show_date = kwargs.get('show_date', False)
    return {'object_list': qs[0:size], 'show_date': show_date}


@register.inclusion_tag('article/featured.html')
def featured_articles(*args, **kwargs):
    '''
    获取特色文章
    用法举例:
       1. featured_articles
       2. featured_articles 1
       3. featured_articles news
       4. featured_articles category
       5. ........................ size = 10
    用法1 显示所有特色文章；
    用法2、3、4 显示指定分类及其子分类的特色文章
    用法5 指定获取的文章数量
    '''
    category, size = _parse_category_fetch_size(*args, **kwargs)
    show_date = kwargs.get('show_date', False)
    if category:
        if kwargs.get('include_children', False):
            categories = list(category.children.all())
        else:
            categories = []
        categories.append(category)
        return {
            'object_list': Article.objects.filter(featured=True, categories__in=categories).order_by('-publish_date')[
                           0:size],
            'show_date': show_date
        }
    else:
        return {'object_list': Article.objects.filter(featured=True).order_by('-publish_date')[0:size],
                'show_date': show_date
        }


@register.assignment_tag(takes_context=True)
def paginate_objects(context, objects, *args, **kwargs):
    request = context['request']
    per_page = 10
    if args:
        try:
            per_page = int(args[0])
        except ValueError:
            pass
    if isinstance(objects, Manager):
        paginator = Paginator(objects.all(), per_page)
    else:
        paginator = Paginator(objects, per_page)
    page = request.GET.get('page', 1)
    page_obj = paginator.page(page)

    return page_obj